#!/usr/bin/perl -w
use strict;
use warnings;
use Getopt::Long;
use IO::File;

my %opt;

GetOptions(\%opt,
  'targets=s',
  'with-bloaty',
  'upx=s',
) or die "Error in command line arguments\n";

my @targets = split /,/, $opt{targets};

my @compilers = qw(
    gcc
    clang
    clang-lto
    clang-minsize-lto
);

my %target_compilers = (
    # https://github.com/llvm/llvm-project/issues/150913
    ppc64   => [qw(gcc)],
    ppc64le => [qw(gcc)],
);

my $WITH_CACHES = "--mount=type=cache,id=ccache,target=/root/.ccache --mount=type=cache,id=pkgcache,target=/root/.pkgcache";

my $INSTALL_BLOATY = '';

if ($opt{'with-bloaty'}) {
    $INSTALL_BLOATY = <<BLOATY;

# Install bloaty
COPY install-bloaty.sh /usr/local/bin/install-bloaty.sh
RUN $WITH_CACHES \\
    bash /usr/local/bin/install-bloaty.sh
BLOATY
}

print <<ENDHEADER;
# syntax=docker/dockerfile:1
#
###############################################################################
#
# DO NOT EDIT THIS FILE DIRECTLY!
#
# IT WAS GENERATED BY $0
#
###############################################################################

FROM alpine:latest AS base

RUN apk update
RUN apk upgrade
RUN apk add --no-cache \\
        bash-completion \\
        build-base \\
        wget \\
        curl \\
        vim \\
        tar \\
        ripgrep \\
        less \\
        gcc \\
        g++ \\
        clang20 \\
        lld \\
        git \\
        xz \\
        gzip \\
        bzip2 \\
        zstd \\
        ccache \\
        ninja-build \\
        cmake \\
        make \\
        bison \\
        flex \\
        ronn \\
        perf \\
        py3-pip \\
        py3-xxhash \\
        py3-zstd \\
        py3-lz4 \\
        fuse \\
        fuse3 \\
        pkgconf \\
        meson \\
        autoconf \\
        strace \\
        gdb \\
        gmp-dev \\
        zlib-static \\
        zstd-static \\
        zlib-dev \\
        zstd-dev \\
        mpfr-dev \\
        mpc1-dev \\
        isl-dev \\
        texinfo \\
        linux-headers \\
        gdb-multiarch \\
        rsync \\
        screen \\
        qemu-arm \\
        qemu-armeb \\
        qemu-i386 \\
        qemu-mips \\
        qemu-mipsel \\
        qemu-ppc \\
        qemu-riscv32 \\
        qemu-sparc \\
        qemu-aarch64 \\
        qemu-aarch64_be \\
        qemu-alpha \\
        qemu-hppa \\
        qemu-loongarch64 \\
        qemu-mips64 \\
        qemu-mips64el \\
        qemu-ppc64 \\
        qemu-ppc64le \\
        qemu-riscv64 \\
        qemu-s390x \\
        qemu-sparc64

COPY fetch.sh /usr/local/bin/fetch.sh

# Install mold
COPY install-mold.sh /usr/local/bin/install-mold.sh
RUN $WITH_CACHES \\
    bash /usr/local/bin/install-mold.sh
$INSTALL_BLOATY
RUN apk del linux-headers

FROM base AS build_base

COPY toolchain-versions.sh /usr/local/bin/toolchain-versions.sh
COPY toolchain-prepare.sh /usr/local/bin/toolchain-prepare.sh
COPY toolchain-install.sh /usr/local/bin/toolchain-install.sh

RUN $WITH_CACHES \\
    bash /usr/local/bin/toolchain-prepare.sh

###############################################################################

FROM base AS staticlibs_base

COPY static-libs-versions.sh /usr/local/bin/static-libs-versions.sh
COPY static-libs-fetch.sh /usr/local/bin/static-libs-fetch.sh

RUN $WITH_CACHES \\
    bash /usr/local/bin/static-libs-fetch.sh

ENDHEADER

my @toolchains;
my @staticlibs;

for my $target (@targets) {
    my $toolchain_stage = "toolchain_$target";
    push @toolchains, $toolchain_stage;

    print <<ENDTARGET;
###############################################################################

FROM build_base AS $toolchain_stage

RUN $WITH_CACHES \\
    bash /usr/local/bin/toolchain-install.sh 2 $target

RUN apk del zlib-dev zstd-dev

ENDTARGET

    my $tcs = $target_compilers{$target} // \@compilers;

    for my $compiler (@$tcs) {
        my $staticlibs_stage = "staticlibs_${target}_$compiler";
        push @staticlibs, $staticlibs_stage;

        print <<ENDCOMPILER;
###############################################################################

FROM $toolchain_stage AS $staticlibs_stage

COPY --link --from=staticlibs_base /root/pkgs/ /root/pkgs/

COPY static-libs-versions.sh /usr/local/bin/static-libs-versions.sh
COPY static-libs-install.sh /usr/local/bin/static-libs-install.sh

RUN $WITH_CACHES \\
    bash /usr/local/bin/static-libs-install.sh :all $target $compiler

ENDCOMPILER
    }
}

print <<ENDFINAL;
###############################################################################

FROM base AS final

ENDFINAL

for my $tc (@toolchains) {
    print "COPY --link --from=$tc /opt/cross/ /opt/cross/\n";
}

for my $sl (@staticlibs) {
    print "COPY --link --from=$sl /opt/static-libs/ /opt/static-libs/\n";
}

if ($opt{upx}) {
    print <<ENDUPX;

# Install UPX
RUN $WITH_CACHES \\
    /usr/local/bin/fetch.sh https://github.com/upx/upx/releases/download/v5.0.2/upx-5.0.2-$opt{upx}_linux.tar.xz - \\
        | tar -xJf - -C /usr/local/bin --strip-components=1 --wildcards "*/upx"
ENDUPX
}

print <<ENDFINAL;

RUN pip3 install --break-system-packages --root-user-action ignore mistletoe

# Set up git & user
RUN git config --global --add safe.directory /workspace
RUN adduser -G users -s bash -u 1000 -D mhx
USER mhx
ENTRYPOINT /workspace/.docker/build-linux.sh
ENDFINAL
